Passed
Push — master ( 78b380...a2100d )
by Rafael
01:41
created

control.js ➔ ???   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 18
Bugs 0 Features 0
Metric Value
cc 2
c 18
b 0
f 0
nc 2
dl 0
loc 11
rs 9.4285
nop 1
1
var $ = window.jQuery;
2
import './style.scss';
3
import { Slider } from '../slider';
4
import { Conversion } from './conversion';
5
import template from './template.html';
6
import config from './config.js';
7
import deepmerge from 'deepmerge';
8
import refreshSvg from 'svg-inline-loader?classPrefix!./img/refresh.svg';
9
import linkSvg from 'svg-inline-loader?classPrefix!./img/link.svg';
10
11
export class MultiSlider {
12
	constructor( options ) {
13
		this.options = options || {};
14
15
		this.slidersLinked = false;
16
		this.$target = this.options.target;
17
		this.template = _.template( template );
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
18
19
		if ( ! this.$target ) {
20
			throw Error( 'Your must define a target element' );
21
		}
22
	}
23
24
	/**
25
	 * Merge the default configurations with any requested by a child class.
26
	 *
27
	 * @since 1.0.0
28
	 */
29
	mergeDefaultConfigs() {
30
		this.controlOptions = deepmerge( config.defaults, this.controlOptions, {
31
			arrayMerge: ( destination, source ) => source
32
		} );
33
	}
34
35
	/**
36
	 * Return a jQuery control.
37
	 *
38
	 * @since 1.0
39
	 *
40
	 * @return {jQuery} Control.
41
	 */
42
	render() {
43
		this.mergeDefaultConfigs();
44
45
		this.controlOptions.svg = {};
46
		this.controlOptions.svg.link = linkSvg;
47
		this.controlOptions.svg.refresh = refreshSvg;
48
49
		this.$control = $( this.template( this.controlOptions ) );
50
		this.$sliderGroup = this.$control.find( '.slider-group' );
51
		this.$units = this.$control.find( '.unit' );
52
		this.$revert = this.$control.find( '.refresh' );
53
54
		this._bindUnits();
55
		this.setUnits( this.controlOptions.control.units.default );
56
57
		// Create sliders and attach them to the template.
58
		this._createSliders();
59
		this.$links = this.$control.find( '.link' );
60
61
		this._storeDefaultValues();
62
		this._setDefaultLinkedState();
63
		this._bindLinked();
64
		this._bindRevert();
65
66
		return this.$control;
67
	}
68
69
	/**
70
	 * Apply the settings to the control.
71
	 *
72
	 * @since 1.0
73
	 *
74
	 * @param  {object} settings Settings.
75
	 */
76
	applySettings( settings ) {
77
		this.setUnits( settings.unit );
78
79
		for ( let key in settings.values ) {
80
			let value = settings.values[key];
81
82
			this.sliders[key].$slider.slider( 'option', 'value', value );
83
		}
84
	}
85
86
	/**
87
	 * Update the target.
88
	 *
89
	 * @since 1.0
90
	 *
91
	 * @param  {jQuery} $target New Target.
92
	 */
93
	updateTarget( $target ) {
94
		this.$target = $target;
95
	}
96
97
	/**
98
	 * Set the unit to use.
99
	 *
100
	 * @since 1.0
101
	 *
102
	 * @param {string} unit Units.
103
	 */
104
	setUnits( unit ) {
105
		this.$units
106
			.filter( '[value="' + unit + '"]' )
107
			.prop( 'checked', true )
108
			.change();
109
	}
110
111
	/**
112
	 * Get the values.
113
	 *
114
	 * @since 1.0
115
	 *
116
	 * @return {Object} Current values for each direction.
117
	 */
118
	getValues() {
119
		let values = {};
120
121
		for ( let name in this.sliders ) {
122
			values[name] = this.sliders[name].$slider.slider( 'value' );
123
		}
124
125
		return values;
126
	}
127
128
	/**
129
	 * Get a sliders configuration.
130
	 *
131
	 * @since 1.0.0
132
	 *
133
	 * @return {Object} Slider config.
134
	 */
135
	getSliderConfig( slider ) {
136
		let settings = this.controlOptions.slider[this.selectedUnit],
137
			value = this.convertToSelectedUnit( this.$target.css( slider.cssProperty ) );
138
139
		settings.value = value;
140
		return settings;
141
	}
142
143
	/**
144
	 * Convert the JS pixel value to perctenage or ems.
145
	 *
146
	 * @since 1.0.0
147
	 *
148
	 * @param  {string} rawValue JS computed value.
0 ignored issues
show
Documentation introduced by
The parameter rawValue does not exist. Did you maybe forget to remove this comment?
Loading history...
149
	 * @return {integer}          New Value.
150
	 */
151
	convertToSelectedUnit( computedValue ) {
152
		let pixelValue = parseInt( computedValue ),
153
			converted = pixelValue;
154
155
		if ( '%' === this.selectedUnit ) {
156
			converted = new Conversion().pxToPercentage( pixelValue, this.$target.parent() );
157
		} else if ( 'em' === this.selectedUnit ) {
158
			converted = new Conversion().pxToEm( pixelValue, this.$target.css( 'font-size' ) );
159
		}
160
161
		return converted;
162
	}
163
164
	/**
165
	 * Create sliders and attach them to the template.
166
	 *
167
	 * @since 1.0.0
168
	 */
169
	_createSliders() {
170
		this.sliders = {};
171
172
		for ( let slider of this.controlOptions.control.sliders ) {
173
			let sliderControl;
174
175
			slider.uiSettings = this.getSliderConfig( slider );
176
			sliderControl = new Slider( $.extend( true, {}, slider ) );
177
178
			sliderControl.render();
179
180
			this.$sliderGroup.append( sliderControl.$control );
181
			sliderControl.$input.after( '<a class="link" href="#">' + linkSvg + '</a>' );
182
183
			this.sliders[slider.name] = sliderControl;
184
185
			this._bindSliderChange( sliderControl );
186
		}
187
	}
188
189
	/**
190
	 * Save the default values for reverts.
191
	 *
192
	 * @since 1.0
193
	 */
194
	_storeDefaultValues() {
195
		this.defaultValues = {
196
			unit: this.controlOptions.control.units.default,
197
			values: this.getValues()
198
		};
199
	}
200
201
	/**
202
	 * Bind reverting changes to original.
203
	 *
204
	 * @since 1.0
205
	 */
206
	_bindRevert() {
207
		this.$revert.on( 'click', event => {
208
			event.preventDefault();
209
			this.applySettings( this.defaultValues );
210
		} );
211
	}
212
213
	/**
214
	 * Bind changing of units.
215
	 *
216
	 * @since 1.0
217
	 */
218
	_bindUnits() {
219
		this.$control.find( '.unit' ).on( 'change', e => {
220
			let $target = $( e.target );
221
222
			this.selectedUnit = $target.val();
223
			if ( this.sliders ) {
224
				this.updateSliderConfigs();
225
			}
226
		} );
227
	}
228
229
	/**
230
	 * Update the slider configurations based on new units.
231
	 *
232
	 * @since 1.0.0
233
	 */
234
	updateSliderConfigs() {
235
		this.linkedDisabled = true;
236
		for ( let slider of this.controlOptions.control.sliders ) {
237
			let options = this.getSliderConfig( slider );
238
239
			this.sliders[slider.name].$slider.slider( 'option', options );
240
		}
241
242
		setTimeout( () => {
243
			this.linkedDisabled = false;
244
		} );
245
	}
246
247
	/**
248
	 * Set the default slider state.
249
	 *
250
	 * @since 1.0.0
251
	 */
252
	_setDefaultLinkedState() {
253
		if ( this.controlOptions.control.linkable ) {
254
			let values = _.unique( _.values( this.getValues() ) );
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
255
			this.slidersLinked = ( 1 === values.length );
256
		}
257
	}
258
259
	/**
260
	 * Bind the user linking the controls.
261
	 *
262
	 * @since 1.0.0
263
	 */
264
	_bindLinked() {
265
		if ( this.slidersLinked ) {
266
			this.$links.addClass( 'linked' );
267
		}
268
269
		this.$links.on( 'click', event => {
270
			let $target = $( event.target ).closest( 'a' );
271
			event.preventDefault();
272
			$target.toggleClass( 'linked' );
273
			this.slidersLinked = $target.hasClass( 'linked' );
274
			this.$control.trigger( 'linked', { isLinked: this.slidersLinked } );
275
		} );
276
	}
277
278
	/**
279
	 * Updated linked sliders.
280
	 *
281
	 * @since 1.0.0
282
	 *
283
	 * @param  {Slider} updatedSlider Slider that was updated by user.
284
	 */
285
	_updateLinked( updatedSlider ) {
286
		if ( this.slidersLinked && ! this.linkedDisabled ) {
287
			this.linkedDisabled = true;
288
289
			_.each( this.sliders, slider => {
0 ignored issues
show
Bug introduced by
The variable _ seems to be never declared. If this is a global, consider adding a /** global: _ */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
290
				if ( updatedSlider !== slider ) {
291
					slider.$slider.slider( 'value', updatedSlider.$slider.slider( 'value' ) );
292
				}
293
			} );
294
		}
295
296
		setTimeout( () => {
297
			this.linkedDisabled = false;
298
		} );
299
	}
300
301
	/**
302
	 * Update the css that a single slider controls
303
	 *
304
	 * @since 1.0.0
305
	 *
306
	 * @param  {Slider} slider Slider class.
307
	 */
308
	_updateCss( slider ) {
309
		let property = {};
310
		property[slider.options.cssProperty] = slider.$slider.slider( 'value' ) + this.selectedUnit;
311
		this.applyCssRules( property );
312
	}
313
314
	applyCssRules( property ) {
315
		this.$target.css( property );
316
	}
317
318
	/**
319
	 * Update css as the control fires updates.
320
	 *
321
	 * @since 1.0.0
322
	 */
323
	_bindSliderChange( slider ) {
324
		slider.$control.on( 'slide-change', ( e, data ) => {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter data is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
325
			this._updateLinked( slider );
326
			this._updateCss( slider );
327
		} );
328
	}
329
}
330
331
export { MultiSlider as default };
332